import { Injectable, ComponentFactoryResolver, ComponentRef } from '@angular/core';
import { Subject } from 'rxjs';
import { Condition } from 'src/app/models';
import { BaseFieldComponent } from '../components/fields/base-field/base-field.component';
import { RenderComponentConfig } from '../models/render-component-config';

@Injectable({
  providedIn: 'root'
})
export class EngineService {

  currentDataModel: any = {};

  /**
   * 用于映射供应商服务系统的字段
   */
  mapDataModel: any = {};

  constructor(
    private componentFactoryResolver: ComponentFactoryResolver
  ) { }
  /**
   * 组件数据变化的通知
   */
  dataModelChange$: Subject<DataModelChange> = new Subject<DataModelChange>();
  componentRenderChanged$: Subject<IComponentRenderChangedArgs> = new Subject<IComponentRenderChangedArgs>();
  componentHide$: Subject<IComponentHideArgs> = new Subject<IComponentHideArgs>();
  /**
   * 组件显示条件变化的通知
   */
  componentConditionChange$: Subject<Condition> = new Subject<Condition>();
  /**
   * 具备超级编辑权限时，编辑只读节点的通知
   */
  superAuthEdit$: Subject<boolean> = new Subject<boolean>();
  /**
   * 组件渲染完成的通知
   */
  renderComplete$: Subject<ComponentRef<BaseFieldComponent>> = new Subject<ComponentRef<BaseFieldComponent>>();
  /**
   * 模板是否具有权限的通知
   * templateItemId
   */
  templateAuthChange$: Subject<{ templateItemId: string; isUnAuthorized: boolean; }> = new Subject<{ templateItemId: string; isUnAuthorized: boolean; }>();
  componentRefs: ComponentRef<BaseFieldComponent>[];
  fieldErrors?: {
    identifyId: string;
    inValid: boolean;
    errors: any;
    name?: string;
    errorMsg?: string;
    expanded?: boolean; // 是否是扩展验证
    value?: any;
  }[];
  /**
   *  渲染一个组件
   */
  renderComponent(renderComponentConfig: RenderComponentConfig, tmpComItemId?: string) {
    const renderItem = renderComponentConfig.renderItem;
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(renderItem.component);
    renderComponentConfig.viewContainerRef.clear();
    const componentRef: ComponentRef<BaseFieldComponent> = renderComponentConfig.viewContainerRef.createComponent(componentFactory);
    // input data
    if (renderItem.componentData) {
      componentRef.instance.componentData = renderItem.componentData;
    }
    // 双向绑定的数据模型
    // if (renderItem.dataModel) {
    //   componentRef.instance.dataModel = renderItem.dataModel;
    // }

    // output event
    if (renderItem.event) {
      componentRef.instance.innerEvent.subscribe((data: any) => {
        renderItem.event(data);
      });
    }

    componentRef.instance.tmpComItemId = tmpComItemId;
    componentRef.changeDetectorRef.detectChanges();
    if (!this.componentRefs || !this.componentRefs.length) {
      this.componentRefs = [];
    }
    this.componentRefs.push(componentRef);
    this.renderComplete$.next(componentRef);
    return componentRef;
  }

  clear() {
    this.fieldErrors = null;
    this.componentRefs = [];
  }
  /**
   * 校验组件绑定数据
   */
  async validateComponents(params?: {
    objectId?: string;
    dataType: string;
    objectType: 'page' | 'workflow'
  }) {
    this.fieldErrors = [];
    if (Array.isArray(this.componentRefs) && this.componentRefs.length) {
      for (const item of this.componentRefs) {
        await item.instance.validate(params);
      }
    }
    if (this.fieldErrors && this.fieldErrors.length) {
      const id = this.fieldErrors[0].identifyId;
      const componentRef = this.componentRefs.find(item => item.instance.componentData.identifyId === id);
      if (componentRef) {
        componentRef.changeDetectorRef.detectChanges();
        const errorDom = document.querySelector('.has-form-error');
        // tslint:disable-next-line: no-unused-expression
        errorDom && errorDom.scrollIntoView({ behavior: 'smooth' });
      }
    }
    else if (this.componentRefs && this.componentRefs.length) {
      for (const ref of this.componentRefs) {
        if (ref.instance.pageSavedHandle) {
          // console.log('nnnnnnn', ref.instance.);
          await ref.instance.pageSavedHandle();
        }
      }
    }
    return this.fieldErrors;
  }

  notifyConditionChange(condition: Condition) {
    this.componentConditionChange$.next(condition);
  }
  /**
   * 通知修改事件
   */
  notifySuperEdit() {
    this.superAuthEdit$.next(true);
  }
  /**
   * 模板是否不具备权限的通知
   */
  notifyTemplateAuth(params: {
    templateItemId: string;
    isUnAuthorized: boolean;
  }) {
    this.templateAuthChange$.next(params);
  }
}

interface DataModelChange {
  bindField: string;
  value?: any;
  identifyId?: string;
  tmpComItemId?: string;
  dataModel: any;
  selector?: string;
}

interface IComponentRenderChangedArgs {
  actionType: 'show' | 'other';
  isShow?: boolean;
  condition?: Condition;
}

interface IComponentHideArgs {
  tmpComItemId: string;
}
